package GUI;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeMap;

import Control.Airport;
import Control.Meteor;
import Control.MilitaryBase;
import Control.PopDensity;
import Control.Shape;
import Control.UFO;
import Control.WeatherStation;

public class DataClass {

	ArrayList<UFO> ufos = new ArrayList<UFO>();

	ArrayList<ArrayList<ArrayList<ArrayList<UFO>>>> wholeUfos = new ArrayList<ArrayList<ArrayList<ArrayList<UFO>>>>();

	HashMap<String, TreeMap> shapeSightings = new HashMap<String, TreeMap>();
	HashMap<String, ArrayList> yearsSightings = new HashMap<String, ArrayList>();
	HashMap<String, ArrayList> monthsSightings = new HashMap<String, ArrayList>();

	ArrayList<WeatherStation> stations=new ArrayList<WeatherStation>();
	ArrayList<ArrayList<ArrayList<Meteor>>> meteors = new ArrayList<ArrayList<ArrayList<Meteor>>>();

	ArrayList<Airport> airports = new ArrayList<Airport>();
	ArrayList<MilitaryBase> bases = new ArrayList<MilitaryBase>();
	ArrayList<PopDensity> densities=new ArrayList<PopDensity>();

	public DataClass() {
		try {

			loadMilitaryData();
			loadAirportData();
			// loadUfoData();
			loadWholeUfoData();
			loadMeteorData();
			loadDensityData();
			loadStationData();
			
			getDensityData();

		} catch (FileNotFoundException e) {

			e.printStackTrace();
		} catch (IOException e) {

			e.printStackTrace();
		} catch (ClassNotFoundException e) {

			e.printStackTrace();
		} catch (Exception e) {
			
			e.printStackTrace();
		}

	}

	public void loadStationData() throws Exception, ClassNotFoundException
	{
		ObjectInputStream ois=new ObjectInputStream(new FileInputStream(new File("data/stations.ser")));
		stations=(ArrayList<WeatherStation>) ois.readObject();
	}
	public void loadDensityData() throws Exception, IOException
	{
		ObjectInputStream ois=new ObjectInputStream(new FileInputStream(new File("data/density.ser")));
		densities=(ArrayList<PopDensity>) ois.readObject();
	}
	public void loadWholeUfoData() throws FileNotFoundException, IOException,
			ClassNotFoundException {

		ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
				new File("data/finalUfos.ser")));
		wholeUfos = (ArrayList<ArrayList<ArrayList<ArrayList<UFO>>>>) ois
				.readObject();
		System.out.println(wholeUfos.get(0).get(0).get(0).get(0)
				.getDistanceFromClosestAirport());
		System.out.println(wholeUfos.get(0).get(0).get(0).get(0)
				.getClosestAirportId());

	}

	public void loadAirportData() throws FileNotFoundException, IOException,
			ClassNotFoundException {
		ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
				new File("data/airports.ser")));
		airports = (ArrayList<Airport>) ois.readObject();

	}

	public void loadMilitaryData() throws FileNotFoundException, IOException,
			ClassNotFoundException {
		ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
				new File("data/military.ser")));
		bases = (ArrayList<MilitaryBase>) ois.readObject();

	}

	public void loadMeteorData() throws FileNotFoundException, IOException,
			ClassNotFoundException {
		ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
				new File("data/meteors.ser")));
		meteors = (ArrayList<ArrayList<ArrayList<Meteor>>>) ois.readObject();

	}

	public void loadUfoData() {
		try {
			BufferedReader inputReader = new BufferedReader(new FileReader(
					new File("data/ufonew.data")));

			HashMap<String, Integer> shapeMap = new HashMap<String, Integer>();
			int uniqueIndex = 1000;
			while (inputReader.ready()) {

				String inputLine = inputReader.readLine();
				// System.out.println(inputLine);
				String[] inputLineParts = inputLine.split("\t");

				String date = inputLineParts[0].trim();
				int year = 0;
				int month = 0;
				int dayOfMonth = 0;
				int hourOfDay = 0;
				int minute = 0;

				if (date.contains(" ")) {
					String datePart = date.split(" ")[0].trim()
							.replaceAll("\\?", "").replaceAll("-", "");
					String timePart = date.split(" ")[1].trim();

					if (datePart.contains("/")) {
						if (datePart.split("/").length == 3) {
							// if(datePart.split("/")[0].matches("\\d*")&&datePart.split("/")[1].matches("\\d*")&&datePart.split("/")[2].matches("\\d*"))
							{
								if (datePart.split("/")[2].equals("")) {
									year = 0;
								} else {
									year = Integer
											.parseInt(datePart.split("/")[2]);
								}

								if (datePart.split("/")[0].equals("")) {
									month = 0;
								} else {
									month = Integer.parseInt(datePart
											.split("/")[0]);
								}
								if (datePart.split("/")[1].equals("")) {
									dayOfMonth = 0;
								} else {
									dayOfMonth = Integer.parseInt(datePart
											.split("/")[1]);
								}

							}

						}

					}

					if (timePart.contains(":")) {
						hourOfDay = Integer.parseInt(timePart.split(":")[0]);
						minute = Integer.parseInt(timePart.split(":")[1]);
					}

				}
				if (!(year >= 0 && year <= 10)) {
					continue;
				}
				if (inputLineParts.length != 9) {
					continue;
				}
				String city = inputLineParts[1];
				String state = inputLineParts[2];
				String shapeStr = inputLineParts[3];
				String duration = inputLineParts[4];
				String summary = inputLineParts[5];
				String posted = inputLineParts[6];
				float latitude = Float
						.parseFloat(inputLineParts[inputLineParts.length - 2]);
				float longitude = Float
						.parseFloat(inputLineParts[inputLineParts.length - 1]);
				int index;
				if (shapeMap.containsKey(shapeStr)) {
					index = shapeMap.get(shapeStr);
				} else {
					index = ++uniqueIndex;
					shapeMap.put(shapeStr, index);
				}
				GregorianCalendar dateOfSight = new GregorianCalendar(year,
						month, dayOfMonth, hourOfDay, minute);
				processing.core.PVector coordinates = new processing.core.PVector(
						latitude, longitude);
				UFO ufo = new UFO(coordinates, dateOfSight, GV.shapes.get(Shape
						.getShapesEnumFromName(shapeStr).ordinal()), summary,
						duration, city, state,/* LONG SUMMARY TO BE INSERTED HERE */
						"");
				ufos.add(ufo);

				if (shapeSightings.containsKey(shapeStr)) {
					TreeMap<String, TreeMap> yearMonthMap = shapeSightings
							.get(shapeStr);
					if (yearMonthMap.containsKey(month + "/" + year)) {

						TreeMap<Integer, TreeMap> dayMap = yearMonthMap
								.get(month + "/" + year);
						if (dayMap.containsKey(dayOfMonth)) {
							TreeMap<Integer, ArrayList<UFO>> hourMap = (TreeMap) dayMap
									.get(dayOfMonth);

							if (hourMap.containsKey(hourOfDay)) {
								ArrayList<UFO> ufoList = (ArrayList<UFO>) hourMap
										.get(hourOfDay);
								ufoList.add(ufo);
								hourMap.put(hourOfDay, ufoList);
							} else {
								ArrayList<UFO> ufoList = new ArrayList<UFO>();
								ufoList.add(ufo);
								hourMap.put(hourOfDay, ufoList);
							}
							dayMap.put(dayOfMonth, hourMap);
						} else {
							TreeMap<Integer, ArrayList<UFO>> hourMap = new TreeMap(
									new KeyComparator());
							ArrayList<UFO> ufoList = new ArrayList<UFO>();
							ufoList.add(ufo);
							hourMap.put(hourOfDay, ufoList);
							dayMap.put(dayOfMonth, hourMap);
						}
						yearMonthMap.put(month + "/" + year, dayMap);
					} else {
						TreeMap<Integer, TreeMap> dayMap = new TreeMap(
								new KeyComparator());
						TreeMap<Integer, ArrayList<UFO>> hourMap = new TreeMap(
								new KeyComparator());
						ArrayList<UFO> ufoList = new ArrayList<UFO>();
						ufoList.add(ufo);
						hourMap.put(hourOfDay, ufoList);
						dayMap.put(dayOfMonth, hourMap);

						yearMonthMap.put(month + "/" + year, dayMap);

					}
					shapeSightings.put(shapeStr, yearMonthMap);

				} else {
					TreeMap<String, TreeMap> yearMonthMap = new TreeMap(
							new MonthYearComparator());
					TreeMap<Integer, TreeMap> dayMap = new TreeMap(
							new KeyComparator());
					TreeMap<Integer, ArrayList<UFO>> hourMap = new TreeMap(
							new KeyComparator());
					ArrayList<UFO> ufoList = new ArrayList<UFO>();
					ufoList.add(ufo);
					hourMap.put(hourOfDay, ufoList);
					dayMap.put(dayOfMonth, hourMap);
					yearMonthMap.put(month + "/" + year, dayMap);
					shapeSightings.put(shapeStr, yearMonthMap);

				}

			}
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	public ArrayList<ArrayList<ArrayList<Meteor>>> getAllMeteors() {
		return meteors;
	}


	public ArrayList<UFO> getUfoDataByShape(String shapeStr) {
		ArrayList<UFO> ufoList = new ArrayList<UFO>();
		TreeMap<Integer, TreeMap> monthYearMap = shapeSightings.get(shapeStr);
		Set<Integer> monthYearKeys = monthYearMap.keySet();
		Iterator<Integer> monthYearKeysIterator = monthYearKeys.iterator();
		while (monthYearKeysIterator.hasNext()) {
			int monthYearKey = monthYearKeysIterator.next();
			TreeMap<Integer, TreeMap> dayMap = monthYearMap.get(monthYearKey);

			Set<Integer> dayKeys = dayMap.keySet();
			Iterator<Integer> dayKeysIterator = dayKeys.iterator();
			while (dayKeysIterator.hasNext()) {
				int dayKey = dayKeysIterator.next();
				TreeMap<Integer, ArrayList<UFO>> hourMap = dayMap.get(dayKey);

				Set<Integer> hourKeys = hourMap.keySet();
				Iterator<Integer> hourKeysIterator = hourKeys.iterator();

				while (hourKeysIterator.hasNext()) {
					int hourKey = hourKeysIterator.next();
					ArrayList<UFO> ufoHourList = hourMap.get(hourKey);
					for (int j = 0; j < ufoHourList.size(); j++) {
						ufoList.add(ufoHourList.get(j));
					}
				}
			}

		}
		return ufoList;

	}

	public ArrayList<Airport> getAllAirportData() {
		return airports;
	}

	public Airport getAirportDataById(String id) {
		for (int i = 0; i < airports.size(); i++) {
			Airport airport = airports.get(i);
			if (airport.getAirportId().equals(id)) {
				return airport;
			}
		}
		return null;
	}

	public ArrayList<UFO> getAllUfoData() {
		return ufos;
	}

	public ArrayList<MilitaryBase> getAllMilitaryBase() {
		return bases;
	}

	public MilitaryBase getMilitaryBaseByName(String name) {
		for (int i = 0; i < bases.size(); i++) {
			MilitaryBase base = bases.get(i);
			if (base.getName().equals(name)) {
				return base;
			}
		}
		return null;
	}

	public ArrayList<ArrayList<ArrayList<UFO>>> getUfoDataByShape(int index) {
		return wholeUfos.get(index);
	}

	public ArrayList<ArrayList<ArrayList<ArrayList<UFO>>>> getWholeUfoData() {
		return wholeUfos;
	}
	
	public ArrayList<PopDensity> getDensityData()
	{
		
		return densities;
	}
	
	public ArrayList<WeatherStation> getAllWeatherStations()
	{
		return stations;
	}

}
